package juc.blockqueue.linkedblockdeque;

/**
 * @ClassName WorkStealingExample
 * @PackageName juc.blockqueue.linkedblockdeque
 * @projectName myThread
 * @Description 1. 工作窃取算法（Work Stealing）
 * @Author games
 * @Date 2025/9/4 下午3:08
 * @Version 1.0
 */
import java.util.concurrent.LinkedBlockingDeque;
import java.util.Random;

class WorkStealingExample {
/**
 * 工作任务类，表示一个具有ID和复杂度的任务
 */
    static class WorkTask {
        private final String taskId;    // 任务ID
        private final int complexity;    // 任务复杂度

    /**
     * 构造函数，初始化任务ID和复杂度
     * @param taskId 任务ID
     * @param complexity 任务复杂度
     */
        public WorkTask(String taskId, int complexity) {
            this.taskId = taskId;
            this.complexity = complexity;
        }

    /**
     * 获取任务ID
     * @return 任务ID
     */
        public String getTaskId() { return taskId; }
    /**
     * 获取任务复杂度
     * @return 任务复杂度
     */
        public int getComplexity() { return complexity; }

    /**
     * 重写toString方法，返回任务的字符串表示
     * @return 任务的字符串表示
     */
        @Override
        public String toString() {
            return "Task{id='" + taskId + "', complexity=" + complexity + "}";
        }
    }

/**
 * 工作线程类，继承自Thread，用于执行任务
 */
    static class WorkerThread extends Thread {
        private final LinkedBlockingDeque<WorkTask> ownDeque;    // 当前线程自己的任务队列
        private final LinkedBlockingDeque<WorkTask>[] allDeques;  // 所有工作线程的任务队列数组
        private final String workerName;                         // 工作线程名称
        private final Random random = new Random();               // 随机数生成器

    /**
     * 构造函数，初始化工作线程
     * @param ownDeque 当前线程自己的任务队列
     * @param allDeques 所有工作线程的任务队列数组
     * @param workerName 工作线程名称
     */
        public WorkerThread(LinkedBlockingDeque<WorkTask> ownDeque,
                            LinkedBlockingDeque<WorkTask>[] allDeques,
                            String workerName) {
            this.ownDeque = ownDeque;
            this.allDeques = allDeques;
            this.workerName = workerName;
        }

    /**
     * 线程运行方法，实现任务执行和任务窃取逻辑
     */
        @Override
        public void run() {
            try {
                while (true) {
                    // 首先尝试从自己的队列获取任务（从头部）
                    WorkTask task = ownDeque.pollFirst();

                    // 如果自己的队列为空，尝试从其他队列窃取任务（从尾部）
                    if (task == null) {
                        for (LinkedBlockingDeque<WorkTask> deque : allDeques) {
                            if (deque != ownDeque) {
                                task = deque.pollLast();
                                if (task != null) {
                                    System.out.println(workerName + " 窃取了任务: " + task);
                                    break;
                                }
                            }
                        }
                    }

                    // 如果获取到任务，执行它
                    if (task != null) {
                        System.out.println(workerName + " 执行任务: " + task);
                        Thread.sleep(task.getComplexity() * 100); // 模拟任务执行
                    } else {
                        // 没有任务时短暂休眠
                        Thread.sleep(100);
                    }
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }

/**
 * 主方法，创建任务队列、任务和工作线程，并启动工作线程
 */
    public static void main(String[] args) throws InterruptedException {
        // 创建工作队列数组
        LinkedBlockingDeque<WorkTask>[] deques = new LinkedBlockingDeque[3];
        for (int i = 0; i < deques.length; i++) {
            deques[i] = new LinkedBlockingDeque<>();
        }

        // 添加初始任务到各个队列
        deques[0].addLast(new WorkTask("Task-1", 3));
        deques[0].addLast(new WorkTask("Task-2", 2));
        deques[0].addLast(new WorkTask("Task-3", 1));
        deques[1].addLast(new WorkTask("Task-4", 2));
        deques[2].addLast(new WorkTask("Task-5", 1));

        // 创建工作线程数组
        WorkerThread[] workers = new WorkerThread[3];
        for (int i = 0; i < workers.length; i++) {
            workers[i] = new WorkerThread(deques[i], deques, "Worker-" + i);
            workers[i].start();
        }

        Thread.sleep(5000); // 运行5秒后结束程序
    }
}
